FEAT add AgentThreatRulesScorer (ATR taxonomy scorer) - #1893
Conversation
e55c2a6 to
4d55a7d
Compare
|
Freshened this onto the latest main — it is up to date and mergeable now. Ready for review when convenient. |
Adrian Gavrila (adrian-gavrila)
left a comment
There was a problem hiding this comment.
Thanks for picking this up! Overall it looks good, but there are a couple of things that should be addressed, primarily around things actually being excercised in CI and following some style guidelines.
|
Thanks for the thorough review, Adrian — all addressed in the latest push:
Verified locally: ruff passes, and against pyatr 0.2.6 the injection string trips 5 rules (top severity critical) while the benign string trips none, so the severity-floor tests hold. Ready for another look when you have a moment. |
|
Thanks for the thorough review — all points addressed (pushed in 6010cb0). CI exercising the scorer (the root cause): wired Test assertions: the benign path now asserts Severity robustness + casing: the filtered hits are now sorted by our own Style: The checks here are still gated ( |
Adrian Gavrila (adrian-gavrila)
left a comment
There was a problem hiding this comment.
Thanks for addressing those! A couple of things lingering now that we have added this as an optional dependency.
|
Thanks Adrian. All addressed:
With pyatr wired into the atr extra and the all group, the four tests run instead of skipping. I ran them locally against pyatr 0.2.6 and all four pass. |
Adrian Gavrila (adrian-gavrila)
left a comment
There was a problem hiding this comment.
Looks great! Thank you for following up on the comments
|
Pushed a one-line fix (a91bcb4) for the only failing check — the The local The new runs are sitting in |
|
Thanks for the thorough review and the approval, Adrian Gavrila (@adrian-gavrila) — the CI-exercise and style points made the PR better. Is there anything left on your side before it can merge, or is it good to go? Roman Lutz (@romanlutz), since you'd asked about the scorer over on #1702 — this is it, approved and ready whenever you'd like to bring it in. |
d123692 to
59c2996
Compare
|
Adrian Gavrila (@adrian-gavrila) — heads up that I force-pushed this branch. It had drifted 102 commits behind main and was conflicting, so it could not merge despite your approval on 2026-06-16, and it has been sitting since. Rebuilt on current main rather than merged. The conflicts were all in The content you approved is unchanged. The diff against main is still 5 files, +245/-1, matching the original exactly:
Tests pass locally (4 passed). If the force-push invalidated your approval on GitHub's side, could you re-approve when you have a moment? Happy to walk through the rebuild if you would rather verify it independently first. |
Add a deterministic TrueFalseScorer that evaluates text against the open Agent Threat Rules (ATR) ruleset via the pyatr engine and returns True when a rule at or above a configurable min_severity matches, attaching matched rule ids / ATR category / max severity as score metadata. Mirrors SubStringScorer; pyatr (>=0.2.6) is an optional dependency. Scorer half of Signed-off-by: Adam Lin <adam@agentthreatrule.org>
…ertions
- Sort hits by severity explicitly; don't rely on pyatr internal ordering
- Add pyatr>=0.2.6 as an optional 'atr' extra + into 'all' so CI installs it
- Ungate test_atr_scorer_rejects_invalid_min_severity (no engine needed);
gate the three engine tests individually with skipif
- Fix benign assertion (== {}), drop vacuous 'is not None'
- _build_identifier includes rules_dir
- ruff: Optional -> X | None, add Raises/Returns, D213
Addresses the remaining review note: the severity filter/sort lowercases before comparing, so store the lowercased value in max_severity (and the description) too — correct even if pyatr emits mixed-case severities.
…rror guard, regen uv.lock Per @adrian-gavrila's 2026-06-15 review: - test: collapse skipif to one line via is_pyatr_installed() helper (mirrors is_opencv_installed); ruff format clean - scorer: install hint -> pip install pyrit[atr] (docstring + ImportError msg) - scorer: narrow import guard to ModuleNotFoundError - regen uv.lock so the pyatr extra resolves in CI
59c2996 to
de9c5d4
Compare
|
Adrian Gavrila (@adrian-gavrila) — rebased onto current I did not just rebase and ping, because a green CI expires once the base moves. Re-verified on latest
Three things worth flagging from the rebase, in case any of them changes what you want:
For context on why the scorer matters alongside the loader that merged in #1715: that PR gives PyRIT the ATR payloads on the attack side, but scoring the results still needs an LLM judge. This closes that half deterministically, so a run over a few thousand payloads labels reproducibly and at no token cost. No rush from my side — flagging it only because it was merge-ready and appears to have fallen off the queue rather than been held. |
94251a0 to
de9c5d4
Compare
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Adam Lin (@eeee2345) thank you for keeping this PR up to date, I apologize for the delay here. Going ahead with the merge! |
Adds AgentThreatRulesScorer, the scorer half of #1702 (the dataset loader landed in #1715).
What it does
Dependency
Pairs with the _AgentThreatRulesDataset loader: the dataset supplies ATR-derived adversarial prompts, and this scorer detects whether a response trips an ATR rule.